package ie.lawlor.amvc.swing;

import ie.lawlor.amvc.IDialogEnabledView;
import ie.lawlor.amvc.IView;
import ie.lawlor.amvc.controller.Controller;
import ie.lawlor.amvc.event.Event;
import ie.lawlor.amvc.event.EventName;
import ie.lawlor.amvc.event.ModelUpdatePayload;

import java.awt.Container;
import java.awt.Dimension;

import javax.swing.JDialog;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.JTextComponent;

import org.apache.log4j.Logger;

public abstract class JPanelView extends javax.swing.JPanel implements SwingDialogEnabledView {
  
  protected SwingDialogEnabledViewProxy viewProxy;
  protected Logger logger;
  protected int fieldBeingEdited = -1;
  
  // Is not technically abstract, but should only be instanciated by a derived class. 
  protected JPanelView(String name){
    viewProxy = new SwingDialogEnabledViewProxy(name, this);
    logger = viewProxy.getLogger();
  }
  
  protected JPanelView(){
    viewProxy = new SwingDialogEnabledViewProxy(this);
    logger = viewProxy.getLogger();
  }
  
  /* (non-Javadoc)
   * @see com.informatica.amvc.View#setViewVisible(boolean)
   */
  public void setViewVisible(boolean visible) {
    logger.info("Setting view " + getName() + " visible: " + visible);
    viewProxy.setViewVisible(visible);
  }
  
  /* (non-Javadoc)
   * @see com.informatica.amvc.DialogEnabledView#setUsingDialog(boolean)
   */
  public void setUsingDialog(boolean usingDialog) {
    viewProxy.setUsingDialog(usingDialog);
  }
  
  /* (non-Javadoc)
   * @see com.informatica.amvc.DialogEnabledView#setModel(boolean)
   */
  public void setModal(boolean modal) {
    viewProxy.setModal(modal);
  }
  
  /* (non-Javadoc)
   * @see com.informatica.amvc.DialogEnabledView#setTitle(java.lang.String)
   */
  public void setTitle(String title) {
    viewProxy.setTitle(title);
  }
  
  public void setMinX(int minX){
    setMinimumSize(new Dimension(minX, (int)getMinimumSize().getHeight()));
  }
  
  /* (non-Javadoc)
   * @see com.informatica.amvc.swing.SwingDialogEnabledView#getDialog()
   */
  public JDialog getDialog() {
    return viewProxy.getDialog();
  }
  
  public void eventIn(Event e) {
    viewProxy.eventIn(e);
  }
  
  /* (non-Javadoc)
   * @see com.informatica.amvc.EventSource#fire(com.informatica.amvc.Event)
   */
  public void fire(Event e) {
    viewProxy.fire(e);
  }
  
  /* (non-Javadoc)
   * @see com.informatica.amvc.event.EventSource#fire(com.informatica.amvc.event.EventName, java.lang.Object)
   */
  public void fire(EventName name, Object payload) {
    viewProxy.fire(name, payload);
  }
  
  /* (non-Javadoc)
   * @see com.informatica.amvc.event.EventSource#fire(com.informatica.amvc.event.EventName)
   */
  public void fire(EventName name) {
    viewProxy.fire(name);
  }
  
  /* (non-Javadoc)
   * @see com.informatica.amvc.View#addChild(com.informatica.amvc.View, java.lang.String)
   */
  public void addChild(IView childView, String viewName) {
    viewProxy.addChild(childView, viewName);
  }
  
  /* (non-Javadoc)
   * @see com.informatica.amvc.View#addChild(com.informatica.amvc.View)
   */
  public void addChild(IView childView) {
    viewProxy.addChild(childView);
  }
  
  public void addDialogChild(IDialogEnabledView childView) {
    viewProxy.addDialogChild(childView);
  }
  
  public void setParent(IView parentView) {
    viewProxy.setParent(parentView);
  }
  
  /* (non-Javadoc)
   * @see com.informatica.amvc.View#setParent(com.informatica.amvc.View, java.lang.String)
   */
  public void setParent(IView view, String viewName) {
    viewProxy.setParent(view, viewName);
  }
  
  /* (non-Javadoc)
   * @see com.informatica.amvc.swing.SwingView#getParentView()
   */
  public IView getParentView() {
    return viewProxy.getParentView();
  }
  
  /* (non-Javadoc)
   * @see com.informatica.amvc.View#setController(com.informatica.amvc.Controller)
   */
  public void setController(Controller controller) {
    viewProxy.setController(controller);
  }
  
  public Controller getController(){
    return viewProxy.getController();
  }
  
  public void setName(String name){
    viewProxy.setName(name);
  }
  
  public void doInitView(Event e) {
    viewProxy.doInitView(e);
  }
  
  public void doHideView(Event e) {
    viewProxy.doHideView(e);
  }
  
  public void doShowView(Event e) {
    viewProxy.doShowView(e);
  }
  
  /* (non-Javadoc)
   * @see com.informatica.amvc.swing.SwingView#getContainer(java.lang.String)
   */
  public Container getContainer(String viewName) {
    return this;
  }
  
  protected void fireUpdateModel(int fieldId, Object value){
    if (!updatingView){
      fire(getController().getEvent(Controller.UPDATEMODEL), new ModelUpdatePayload(fieldId, value));
    }
  }
  
  /**
   * Adds a listener to a text component to allow the model to track any changes to
   * the contents of the text component on a character by character basis.
   */
  protected void addTextComponentListener(final JTextComponent textComponent, 
          final int fieldId){
    textComponent.getDocument().addDocumentListener(new DocumentListener(){
      public void insertUpdate(DocumentEvent e) {
        anyUpdate();
      }
      public void removeUpdate(DocumentEvent e) {
        anyUpdate();
      }
      public void changedUpdate(DocumentEvent e) {
        anyUpdate();
      }
      private void anyUpdate(){
        if (!JPanelView.this.updatingView) {
          if (fieldBeingEdited == -1){
            fieldBeingEdited = fieldId;
            fireUpdateModel(fieldBeingEdited, textComponent.getText());
            fieldBeingEdited = -1;
          }
        }
      }
    });
  }
  
  protected boolean updatingView = false;
  
}
